package com.tim.javaApi.reflect;

import com.mysql.cj.jdbc.Driver;

import org.openjdk.jol.info.ClassLayout;
import org.springframework.util.ReflectionUtils;
import sun.security.ec.SunEC;

import java.lang.reflect.Field;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;

/**
 * @Description:
 * @Version 1.0, 2021/9/25
 * @Author Tim
 */
public class ReflectDemo {
    ReflectionUtils reflectionUtils;// spring反射工具

    
    public void printClass(){
        Object object = new ReflectDemo();
        String clazzName = object.getClass().getName();
        System.out.println(clazzName);

    }

    
    public void classLoader() throws SQLException {
        ClassLoader classLoader;
        // bootstrap 输出为null
        Object object = new Object();
        System.out.println(object.getClass().getClassLoader());
        object = new String();
        System.out.println(object.getClass().getClassLoader());
        // ext
        object = new SunEC();
        System.out.println(object.getClass().getClassLoader());
        // app
        object = new ReflectDemo();
        System.out.println(object.getClass().getClassLoader());
        // app
//        object = new AdminParamResp();
//        System.out.println(object.getClass().getClassLoader());
        // app，bootstrap委托给线程上下文加载器加载
        object = new Driver();
        System.out.println(object.getClass().getClassLoader());

    }

    
    public void printObjMemory() throws Exception {
        Object object = new Req();
        String str = ClassLayout.parseInstance(object).toPrintable();// 打印obj对象头
        System.out.println(str);
    }

    
    public void modifyFinal() throws Exception {
        Req req = new Req();
        System.out.println(req.map);
        Field f = Req.class.getField("map");
        f.setAccessible(true);
        Map map = new HashMap();
        map.put(1, 1);
        f.set(req, map);
        System.out.println(req.map);

        // 反射是可以修改final变量的，但是如果是基本数据类型或者String类型的时候，无法通过对象获取修改后的值，因为JVM对其进行了内联优化
        System.out.println(req.i1);
        Field f1 = Req.class.getField("i1");
        f1.setAccessible(true);
        f1.set(req, 2);
        System.out.println(req.i1);
        System.out.println(f1.get(req));

        Field f2 = Req.class.getDeclaredField("i0");
        f2.setAccessible(true);
        System.out.println(f2.get(req));
    }


    class Req {
        public final Map map=new HashMap();
        public final int i1=0;
        private int i0=3;
        boolean b1;
        long l1;
        int i2;
        double d1;
        long l2;
        short s1;
        byte by1;
        byte by2;

        public class InnerReq {
            int j;
            // java8不允许成员内部类有静态变量、静态块
//            static int j2;
//            static {
//                System.out.println("InnerReq");
//            }
        }
    }
}
